//
//  MidiController.m
//  FlashController
//
//  Created by Martin Schiøth Dyrby on 8/16/12.
//  Copyright 2012 Molamil. All rights reserved.
//

#import "MidiController.h"
#include "RtMidi.h"

@implementation MidiController

@synthesize nextControlListeners;
@synthesize controlListeners;
@synthesize stepControlListeners;
@synthesize decrementValue;
@synthesize incrementValue;

RtMidiIn *midiin = 0;

- (void) init{
    
    NSLog(@"MidiController init");
	
	nextControlListeners =	[[NSMutableArray alloc] init];
	controlListeners =		[[NSMutableArray alloc] init];
	stepControlListeners =	[[NSMutableArray alloc] init];
	
	decrementValue = [NSNumber numberWithInt: 40];
	incrementValue = [NSNumber numberWithInt: 87];
	
	try {
		midiin = new RtMidiIn();
        
		midiin->openPort( 0 );
        
		midiin->ignoreTypes( false, false, false );
        
		unsigned int nPorts = midiin->getPortCount();
        
		std::string portName;
		for ( unsigned int i=0; i<nPorts; i++ ) {
			try {
				portName = midiin->getPortName(i);
			}
			catch ( RtError &error ) {
				error.printMessage();
			}
		}
	}
	catch (RtError &error) {
		error.printMessage();
	}
    
	if(midiin) {
		[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(checkMidiIn:) userInfo:nil repeats:YES];
	}
}

- (void)checkMidiIn:(NSTimer *) timer {
    
	std::vector<unsigned char> message;
	midiin->getMessage( &message );
	NSArray* listener;	
	NSUInteger i;
	id receiver;
	NSString* aSelectorName;
	NSNumber* controlType;
	NSNumber* controlNum;
	
	int nBytes;
	
	nBytes = message.size();
    
	if ( nBytes > 0) {
		NSNumber* type = [NSNumber numberWithInt: message[0]];
		NSNumber* num = [NSNumber numberWithInt: message[1]];
		NSNumber* value = [NSNumber numberWithInt: message[2]];
        
        
		// check value listeners
		for(i = 0; i < [controlListeners count]; i++) {
			listener = [controlListeners objectAtIndex:i];
			
			controlType = [listener objectAtIndex:0];
			controlNum = [listener objectAtIndex:1];
			aSelectorName = [listener objectAtIndex:2];
			receiver = [listener objectAtIndex:3];	
			
			NSLog(@"%d %d %d %d %@",[controlType intValue],[type intValue],[controlNum intValue],[num intValue],aSelectorName);
			if([controlType intValue] == [type intValue] && [controlNum intValue]== [num intValue]){
				[receiver performSelector:NSSelectorFromString(aSelectorName) withObject: value];
			}
		}
		
        /*
         if(value < decrementValue || value > incrementValue){
         // check step listeners
         for(i = 0; i < [stepControlListeners count]; i++) {
         listener = [stepControlListeners objectAtIndex:i];
         
         controlType = [listener objectAtIndex:0];
         controlNum = [listener objectAtIndex:1];
         aSelectorName = [listener objectAtIndex:2];
         receiver = [listener objectAtIndex:3];	
         
         if(controlType == type && controlNum == num){
         if(value < decrementValue){
         [receiver performSelector:NSSelectorFromString(aSelectorName) withObject: [NSNumber numberWithInt: -1]];
         } else {
         [receiver performSelector:NSSelectorFromString(aSelectorName) withObject: [NSNumber numberWithInt: 1]];
         }
         }
         }
         }
         */
		// Check next control listeners
		for (i = 0; i < [nextControlListeners count]; i++) {
			listener = [nextControlListeners objectAtIndex:i];
			
			aSelectorName = [listener objectAtIndex:0];
			receiver = [listener objectAtIndex:1];
			
			[receiver performSelector:NSSelectorFromString(aSelectorName) withObject: type withObject: num];
		}
		[nextControlListeners removeAllObjects];
	}
}


- (void) addListenerForNextControl: (NSString*) selectorName forObject: (id) receiver{
	BOOL insert = YES;
	for (NSUInteger i = 0; i < [nextControlListeners count]; i++) {
		NSArray* listener = [nextControlListeners objectAtIndex:i];
		NSString* regSelectorName = [listener objectAtIndex:1];
		id regObject = [listener objectAtIndex:2];
		
		if([regSelectorName isEqualToString:selectorName] && regObject==receiver) {
			insert = NO;
			break;
		}
	}
	
	if(insert){
		NSMutableArray* insertArray = [[NSMutableArray alloc] init];
		[insertArray addObject: selectorName];
		[insertArray addObject: receiver];
		
		[nextControlListeners addObject:insertArray];
	}
}
- (void) addListenerForControl: (NSNumber*) controlType withNum: (NSNumber*) controlNum forSelectorName: (NSString*) selectorName forObject: (id) receiver{
	BOOL insert = YES;
    /*	
     for (NSUInteger i = 0; i < [controlListeners count]; i++) {
     NSArray* listener = [controlListeners objectAtIndex:i];
     NSNumber* regType = [listener objectAtIndex: 0];
     NSNumber* regNum = [listener objectAtIndex: 1];
     NSString* regSelectorName = [listener objectAtIndex:2];
     id regObject = [listener objectAtIndex:3];
     
     if(regType==controlType && regNum==controlType && [regSelectorName isEqualToString:selectorName] && regObject==receiver) {
     insert = NO;
     break;
     }
     }
     */
	if(insert){
		NSMutableArray* insertArray = [[NSMutableArray alloc] init];
		[insertArray addObject: controlType];
		[insertArray addObject: controlNum];
		[insertArray addObject: selectorName];
		[insertArray addObject: receiver];
		[controlListeners addObject:insertArray];
	}
}
- (void) addListenerForStepControl: (NSNumber*) controlType withNum: (NSNumber*) controlNum forSelectorName: (NSString*) selectorName forObject: (id) receiver{
	BOOL insert = YES;
	
	for (NSUInteger i = 0; i < [stepControlListeners count]; i++) {
		NSArray* listener = [stepControlListeners objectAtIndex:i];
		NSNumber* regType = [listener objectAtIndex: 0];
		NSNumber* regNum = [listener objectAtIndex: 1];
		NSString* regSelectorName = [listener objectAtIndex:2];
		id regObject = [listener objectAtIndex:3];
		
		if(regType==controlType && regNum==controlType && [regSelectorName isEqualToString:selectorName] && regObject==receiver) {
			insert = NO;
			break;
		}
	}
	if(insert){
		NSMutableArray* insertArray = [[NSMutableArray alloc] init];
		[insertArray addObject: controlType];
		[insertArray addObject: controlNum];
		[insertArray addObject: selectorName];
		[insertArray addObject: receiver];
		[stepControlListeners addObject:insertArray];
	}
}

@end